package com.zou.study.spring.annotation;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;

import java.lang.reflect.Constructor;

/**
 * 决定当前未初始化的组件类型
 *
 * @author _blank
 * @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#predictBeanType(java.lang.Class, java.lang.String)
 * @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(java.lang.Class, java.lang.String)
 * <p>
 * 决定构造器
 * @see org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors(java.lang.Class, java.lang.String)
 * <p>
 * 处理合并bd信息，再修改bean定义信息
 * @see org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Class, java.lang.String)
 * <p>
 * 属性赋值populateBean
 * @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(java.lang.Object, java.lang.String)
 * @see org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor#postProcessProperties(org.springframework.beans.PropertyValues, java.lang.Object, java.lang.String)
 * <p>
 * 组件初始化initializeBean之前的bean有可能被替换
 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
 * <p>
 * <br/>Date 2021/8/23
 * <br/>Time 18:57:51
 */
@Component
public class MyBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor {

    public MyBeanPostProcessor() {
        // org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext)
        System.out.println("何时被实例化了？");
    }

    @Override
    public Class<?> predictBeanType(Class<?> beanClass, @NonNull String beanName) throws BeansException {
        System.out.println(1 + "    " + beanClass.getName() + "    " + beanName);
        return SmartInstantiationAwareBeanPostProcessor.super.predictBeanType(beanClass, beanName);
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, @NonNull String beanName) throws BeansException {
        System.out.println(2 + "    " + beanClass.getName() + "    " + beanName);
        return SmartInstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
    }

    @Override
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, @NonNull String beanName) throws BeansException {
        System.out.println(3 + "    " + "提供构造器" + "    " + beanClass.getName() + "    " + beanName);
        return SmartInstantiationAwareBeanPostProcessor.super.determineCandidateConstructors(beanClass, beanName);
    }

    @Override
    public void postProcessMergedBeanDefinition(@NonNull RootBeanDefinition beanDefinition, Class<?> beanType, @NonNull String beanName) {
        System.out.println(4 + "    " + beanType.getName() + "    " + beanName);
    }

    @Override
    public boolean postProcessAfterInstantiation(@NonNull Object bean, @NonNull String beanName) throws BeansException {
        System.out.println(5);
        return SmartInstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
    }

    @Override
    public PropertyValues postProcessProperties(@NonNull PropertyValues pvs, @NonNull Object bean, @NonNull String beanName) throws BeansException {
        System.out.println(6);
        return SmartInstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
    }

    @Override
    public Object postProcessBeforeInitialization(@NonNull Object bean, @NonNull String beanName) throws BeansException {
        System.out.println(7);
        return SmartInstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(@NonNull Object bean, @NonNull String beanName) throws BeansException {
        System.out.println(8);
        return SmartInstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }

    @Override
    public void resetBeanDefinition(@NonNull String beanName) {
        System.out.println(9);
        MergedBeanDefinitionPostProcessor.super.resetBeanDefinition(beanName);
    }

    @NonNull
    @Override
    public Object getEarlyBeanReference(@NonNull Object bean, @NonNull String beanName) throws BeansException {
        // 返回早期的bean引用，定义三级缓存中的bean信息
        System.out.println("未知");
        return SmartInstantiationAwareBeanPostProcessor.super.getEarlyBeanReference(bean, beanName);
    }

}
